package com.hqd.ch03.v49.boot.autoconfigure;

import com.hqd.ch03.v49.aware.BeanClassLoaderAware;
import com.hqd.ch03.v49.boot.context.annotation.ImportCandidates;
import com.hqd.ch03.v49.context.annotation.Configuration;
import com.hqd.ch03.v49.core.type.classreading.MetadataReader;
import com.hqd.ch03.v49.core.type.classreading.MetadataReaderFactory;
import com.hqd.ch03.v49.core.type.filter.TypeFilter;
import com.hqd.ch03.v49.io.support.SpringFactoriesLoader;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 自动装配过滤类
 */
public class AutoConfigurationExcludeFilter implements TypeFilter, BeanClassLoaderAware {

    private ClassLoader beanClassLoader;

    private volatile List<String> autoConfigurations;

    @Override
    public void setBeanClassLoader(ClassLoader beanClassLoader) {
        this.beanClassLoader = beanClassLoader;
    }

    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
            throws IOException {
        /**
         * 是否配置类且自动装配类
         */
        return isConfiguration(metadataReader) && isAutoConfiguration(metadataReader);
    }

    private boolean isConfiguration(MetadataReader metadataReader) {
        return metadataReader.getAnnotationMetadata().isAnnotated(Configuration.class.getName());
    }

    /**
     * 是否自动装配
     *
     * @param metadataReader
     * @return
     */
    private boolean isAutoConfiguration(MetadataReader metadataReader) {
        /**
         * 包含3.0之后的注解
         */
        boolean annotatedWithAutoConfiguration = metadataReader.getAnnotationMetadata()
                .isAnnotated(AutoConfiguration.class.getName());
        /**
         * 或者SPI中包含对应的配置
         */
        return annotatedWithAutoConfiguration
                || getAutoConfigurations().contains(metadataReader.getClassMetadata().getClassName());
    }

    protected List<String> getAutoConfigurations() {
        if (this.autoConfigurations == null) {
            /**
             * 旧版扫描SPI，自动装配的类
             */
            List<String> autoConfigurations = new ArrayList<>(
                    SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class, this.beanClassLoader));
            //新版扫描SPI，自动装配的类
            ImportCandidates.load(AutoConfiguration.class, this.beanClassLoader).forEach(autoConfigurations::add);
            this.autoConfigurations = autoConfigurations;
        }
        return this.autoConfigurations;
    }

}

